#include "file_uploader.h"

#include "file_task.h"
#include "eventloop.h"
#include "public_define.h"
#include "antianaphylaxis_queue.h"
#include "fileReupload.h"

using namespace DcAdr;

FileUploader &FileUploader::getInstance()
{

    static FileUploader instance;
    return instance;
}
FileUploader::FileUploader()
{
}

FileUploader::~FileUploader()
{
}

// 处理文件上传的核心函数，参数为任务ID、文件列表（JSON格式）、事件编码
void FileUploader::uploadFile(const std::string &taskId, const std::string &files, const std::string &eventCode)
{
    // 1. 日志打印原始文件列表（调试用，查看输入参数）
    Log_Info(files);
    
    // 2. 定义JSON解析器和存储结构
    Json::Reader reader;
    Json::Value jsonfiles;
    
    // 3. 解析files字符串为JSON格式，若解析失败则日志记录并返回
    if (!reader.parse(files, jsonfiles))
    {
        Log_Info("[FileUploader][uploadFile] files parse error, files: {}", files);
        return;
    }
    
    // 4. 检查taskId是否为空，为空则日志记录并返回
    if (taskId.empty())
    {
        Log_Info("[FileUploader][uploadFile] taskId is empty!");
        return;
    }

    // 5. 检查解析后的JSON是否为数组（文件列表应为数组格式），若不是则日志记录并返回
    if (!jsonfiles.isArray())
    {
        Log_Info("[FileUploader][uploadFile] jsonfiles is not array!");
        return;
    }

    // 6. 遍历JSON数组中的每个文件信息
    for (int i = 0; i < jsonfiles.size(); ++i)
    {
        // 7. 获取当前索引的文件信息对象
        auto fileInfo = jsonfiles[i];
        
        // 8. 检查文件信息中的控制器编码是否与本地编码一致（只处理本地设备的文件）
        if (fileInfo["controllerCode"] == global_data::g_controler_code)
        {
            // 9. 从JSON中解析文件路径（通过工具函数JsonToValue转换为string）
            std::string filePath = JsonToValue<std::string>(fileInfo["filePath"]);
            // 10. 从JSON中解析文件名
            std::string fileName = JsonToValue<std::string>(fileInfo["fileName"]);
            // 11. 解析业务类型（若JSON中没有该字段，默认值为"ADR"）
			std::string businessType = fileInfo.isMember("businessType") ? JsonToValue<std::string>(fileInfo["businessType"]) : "ADR";
            
            // 12. 初始化文件优先级为10（默认值）
            int level = 10;
            // 13. 若JSON中包含"level"字段，则更新优先级
            if (fileInfo.isMember("level"))
            {
                level = JsonToValue<int>(fileInfo["level"]);
            }

            // 14. 检查文件路径或文件名是否为空，若为空则日志记录并跳过当前文件
            if (filePath.empty() || fileName.empty())
            {
                Log_Info("[FileUploader][uploadFile] filePath is empty or fileName is empty, filePath:{}, fileName:{}", filePath, fileName);
                continue;
            }

            // 15. 检查文件是否存在（access函数F_OK参数判断存在性）
            if (0 == access(filePath.c_str(), F_OK))
            {
                // 16. 文件存在：调用FileReupload单例记录文件信息（待上传）
                //     参数包括文件路径、任务ID、优先级、事件编码、业务类型
                FileReupload::getInstance().writeFileInfo(filePath, taskId, level, eventCode,businessType);
            }
            else 
            {
                // 17. 文件不存在：检查是否开启了脱敏上传功能
                if (global_data::g_isUploadDesensFile)
                {
                    // 18. 若开启，记录文件路径与任务ID的关联（等待脱敏完成后上传）
                    findAndWriteTaskidInFile(filePath, taskId);
                }
                // 19. 日志记录文件不存在的错误
                Log_ERROR("file:{} not access", filePath);
                
                // 20. 准备文件上传状态信息（用于上报）
                FileUploadParam m_info;
                FileTask tmp;
                m_info.taskId = taskId;
                m_info.fileName = fileName;
                m_info.filePath = filePath;
                m_info.businessType = businessType;
                // 21. 调用FileTask的方法上报文件不存在状态
                tmp.fileUploadStatus(m_info, FileUpLoadStatus_t::FILE_NOT_EXIST);
            }
        }
    }
    return;
}

void FileUploader::findAndWriteTaskidInFile(const std::string &filePath, const std::string &taskId)
{
    auto func = [=]()
    {
        AntianaphylaxisQueue::getInstance().sendUploadStatus2Sts(false);
        AntianaphylaxisQueue::getInstance().findAndWriteTaskidInFile(filePath, taskId);
    };
    appendEvent(ThreadType::E_InVideoAntianaphylaxis, func);
    Log_Info("findAndWriteTaskidInFile run");
    return;
}
